package com.base.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.base.system.base.db.JoinSql;
import com.base.system.config.security.AuthUser;
import com.base.system.config.security.UserKit;
import com.base.system.exception.HttpException;
import com.base.system.jpa.entity.JpaMenu;
import com.base.system.jpa.entity.JpaUserMenu;
import com.base.system.jpa.repository.MenuRepository;
import com.base.system.jpa.repository.UserMenuRepository;
import com.base.system.service.MenuService;
import com.base.system.util.RedisKey;
import com.base.system.util.RedisUtil;
import com.base.system.web.dto.menu.MenuDto;
import com.base.system.web.dto.menu.MenuMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
@Service
public class MenuServiceImpl implements MenuService {
    @Autowired
    private RedisUtil redis;
    @Autowired
    private MenuRepository menuRepository;
    @Autowired
    private UserMenuRepository userMenuRepository;

    @Override
    public List<Long> selectedMenuByUserId(Long userId) {
        List<JpaUserMenu> all = userMenuRepository.findAllByUserId(userId);
        if (CollUtil.isEmpty(all)) return null;
        return all.stream().map(t -> t.getMenuId()).collect(Collectors.toList());
    }

    @Override
    public List<MenuDto> list(MenuDto menu) {
        JoinSql<JpaMenu> sql = JoinSql.genNewSql(JpaMenu.class);
        sql.eqIfHas("id", menu.getId());
        return MenuMapper.toDtos(menuRepository.findAll(sql.build()));
    }

    @Override
    public List<MenuDto> findAllById(Long id) {
        return MenuMapper.toDtos(menuRepository.findAllById(id));
    }

    @Override
    public void save(MenuDto menu) {
        Optional<JpaMenu> url = menuRepository.findFirstByUrl(menu.getUrl());
        if (url.isPresent()) throw new HttpException("菜单url已存在");

        menuRepository.save(MenuMapper.toEntity(menu));
    }

    @Override
    public void update(MenuDto menu) {
        Optional<JpaMenu> jpaMenu = menuRepository.findFirstByUrlAndIdNot(menu.getUrl(), menu.getId());
        if (jpaMenu.isPresent()) throw new HttpException("菜单url已存在");
        JpaMenu jpaMenu1 = MenuMapper.toEntity(menu);
        menuRepository.update(jpaMenu1);
    }

    @Override
    public void delete(Long id) {
        List<JpaMenu> jpaMenus = menuRepository.findAllByParentId(id);
        if (CollUtil.isEmpty(jpaMenus)) throw new HttpException("存在子路径，无法删除");
        menuRepository.deleteById(id);
    }

    @Override
    public void saveUserMenu(List<JpaUserMenu> userMenu) {
        if (CollUtil.isEmpty(userMenu)) throw new HttpException("请勾选至少一项数据");
        userMenuRepository.deleteAllByUserId(userMenu.get(0).getUserId());
        redis.del(UserKit.getCurrentUser().get().getId() + RedisKey.USER_MENU);
        userMenuRepository.saveAll(userMenu);
    }

    @Override
    public List<MenuDto> currentMenu() {
        Optional<AuthUser> currentUser = UserKit.getCurrentUser();
        if (!currentUser.isPresent()) return null;
        Long key = currentUser.get().getId();
        List<JpaUserMenu> userMenus = userMenuRepository.findAllByUserId(key);
        if (CollUtil.isEmpty(userMenus)) return null;
        List<MenuDto> menus = (List<MenuDto>) redis.get(key + RedisKey.USER_MENU);
        if (CollUtil.isEmpty(menus)) {
            List<JpaMenu> allMenu = menuRepository.findAllByIdInIsSibling(userMenus.stream().map(JpaUserMenu::getMenuId).collect(Collectors.toList()));
            //根据父id分组
            Map<Long, List<JpaMenu>> mapGroupParentId = allMenu.stream().filter(t -> t.getParent() != null).collect(Collectors.groupingBy(t -> t.getParent().getId()));
            List<JpaMenu> allParentMenu = allMenu.stream().filter(t -> t.getParent() == null).collect(Collectors.toList());
            for (JpaMenu parentMenu : allParentMenu) {
                List<JpaMenu> jpaMenus = mapGroupParentId.get(parentMenu.getId());
                parentMenu.setChildren(jpaMenus);
            }
            menus = MenuMapper.toDtos(allParentMenu);
            redis.set(key + RedisKey.USER_MENU, menus, redis.expired);
        }
        return menus;
    }

    @Override
    public List<MenuDto> all() {
        return MenuMapper.toDtos(menuRepository.findAllByParentIdNotNull());
    }
}
